/*-----------------------------------------------------------------------------------*/
/* Nuvoton Corporation confidential                                                  */
/*                                                                                   */
/* Copyright (c) 2009 by Nuvoton Corporation                                         */
/* All rights reserved                                                               */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/
/* File Contents:                                                                    */
/*   uart_diag.c                                                                     */
/*                                                                                   */
/* This file contains:                                                               */
/*                                                                                   */
/* Project:                                                                          */
/*                                                                                   */
/* Remark:                                                                           */
/*   1. UART test items without UART0 because it's used by system library            */
/*      sysprintf().                                                                 */
/*   2. UART channel 1 can't be tested on 910B EV board. It's H/W issue.             */
/*   3. The RX trigger level settings are defferent between UART1 and other UART     */
/*      channels.                                                                    */
/*   4. The TX test data without 0x18 because it's a specific character of           */
/*      HyperTerminal. HyperTerminal will reproduce any char that follow 0x18.       */
/*   5. NUC960 don't have PLL1.                                                     */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/ 

#include <stdlib.h>
#include <stdio.h> 
#include <string.h>
 
#include "NUC900_reg.h" 
#include "wblib.h" 
#include "NUC900_uart.h"


//#define CACHE_ON

#define TXCNT	         50  /* For UART_TX() */
#define NUM_OF_BAUDRATE  7

static UART_T param;

/*
	Define test data size for UART_HW_Flowcontrol(), UART_SW_Flowcontrol, UART_RX_MassDATATest(),
	UART_TX_MassDATATest().
*/
#define MASSDATASIZE	(10 * 1024)  // 10KByte 
static UINT8 TXDATA[MASSDATASIZE], RXDATA[MASSDATASIZE];

static UINT8 RX_Test[500];
static UINT8 TX_Test[] = "0123456789";
static UINT8 TX_Test_LB[] = "abcdefghij";
static UINT comBaudRate[NUM_OF_BAUDRATE] = {9600, 38400, 57600, 115200, 230400, 460800, 921600};  

/*-----------------------------------------*/
/* prototypes of static functions          */
/*-----------------------------------------*/
static VOID _UART_ShowErrInfo(INT errno);

/*
	Configure UART settings
*/
static VOID _UART_ConfigureUart(INT nNum);
static VOID _UART_SetChannel(VOID);
static VOID _UART_SetFrequency(VOID);
static VOID _UART_SetBaudrate(VOID);
static VOID _UART_SetDataBit(VOID);
static VOID _UART_SetStopBit(VOID);
static VOID _UART_SetParity(VOID);
static VOID _UART_SetTriggerLevel(INT nNum);

/*
	Test Items
*/
static INT UART_RX(VOID);
static INT UART_TX(VOID);
static VOID UART_GetRegister(VOID);
static VOID UART_Line_Break(VOID);
static VOID UART_Modem_Loopback(VOID);
static VOID UART_SW_Flowcontrol(VOID);   
static VOID UART_HW_Flowcontrol(VOID);
static VOID UART_TX_MassDATATest(VOID);
static VOID UART_RX_MassDATATest(VOID);
static VOID UART_IrDA(VOID);
static VOID UART_High_Speed(VOID);
static VOID UART_High_Speed_External_Loopback(VOID);
static VOID UART_Modem_Test(VOID);  
static VOID UART_External_Loopback(VOID);  /* 2007.11.20 add, PT23 HHWu */  

//------------------------- Program -------------------------//
VOID _UART_TestItem(VOID)
{
	sysprintf("\n\n");
	sysprintf("+-----------------------------------------------------+\n");	
	sysprintf("|              NUC910 UART Test Items                |\n");
	sysprintf("+-----------------------------------------------------+\n");
	sysprintf("| UART External Loopback Test (Verify H/W)      - [0] |\n");
	sysprintf("| UART Receiving Test                           - [1] |\n");
	sysprintf("| UART Transmitting Test                        - [2] |\n");
	sysprintf("| UART get register value                       - [3] |\n");
	sysprintf("| UART Line break Test                          - [4] |\n");
	sysprintf("| UART channel 1 or 3 Modem Loop-back Test      - [5] |\n");
	sysprintf("| UART1 High Speed External Loopback Test       - [6] |\n");
	sysprintf("| UART2 IrDA Test                               - [7] |\n");
	sysprintf("| UART1 modem Test                              - [8] |\n");
	sysprintf("| TX Mass Data Test                             - [a] |\n");
	sysprintf("| RX Mass Data Test                             - [b] |\n");
	sysprintf("| UART1 H/W flow control Test                   - [c] |\n");
	sysprintf("| UART1 S/W flow control Test                   - [d] |\n");
	sysprintf("+-----------------------------------------------------+\n");	
	sysprintf("| Quit                                        - [ESC] |\n");
	sysprintf("+-----------------------------------------------------+\n");
	sysprintf("Select key : \n");
}	 

// HHWu addb    2007.11.20
VOID _UART_Testmsg(INT item)
{
	int ch;
	
	switch(item)
	{
		case 0:
			sysprintf("\n");			
			sysprintf("Description: UART external loopback test. Plug in the RS232 socket that\n");
			sysprintf("             TX/RX closed. If no RS232 socket, program exit test after 1\n");
			sysprintf("             second.\n");
			sysprintf("Test   Tool: RS232 socket.\n");
			sysprintf("H/W Setting: On NUC910 (UART0~4) EV board, set JP1 to select TXD2 or DTR1.\n");
			sysprintf("             Set JP2 to select TXD4 or RIn1. set JP3 to select RXD2 or DSR1.\n");
			sysprintf("             Set JP4 to select RXD4 or CDn1.\n");
			sysprintf("             On NUC920 (UART0~2) EV board, none.\n");
			sysprintf("             On NUC960 (UART0~2) EV board, none.\n");
			sysprintf("Test Result: Porgram should print the test message.\n");		
			break;				
			
		case 1:
			sysprintf("\n");
			sysprintf("Description: UART RX test. Key in 10 characters by hyperterminal.\n");
			sysprintf("Test   Tool: Hyperterminal.\n");
			sysprintf("H/W Setting: On NUC910 (UART0~4) EV board, set JP1 to select TXD2 or DTR1.\n");
			sysprintf("             Set JP2 to select TXD4 or RIn1. set JP3 to select RXD2 or DSR1.\n");
			sysprintf("             Set JP4 to select RXD4 or CDn1.\n");
			sysprintf("             On NUC920 (UART0~2) EV board, none.\n");
			sysprintf("             On NUC960 (UART0~2) EV board, none.\n");
			sysprintf("Test Result: Porgram should print the test message.\n");		
			break;
			
		case 2:
			sysprintf("\n");
			sysprintf("Description: UART TX test. Send data 0~9 to hyperterminal.\n");
			sysprintf("Test   Tool: Hyperterminal.\n");			
			sysprintf("H/W Setting: On NUC910 (UART0~4) EV board, set JP1 to select TXD2 or DTR1.\n");
			sysprintf("             Set JP2 to select TXD4 or RIn1. set JP3 to select RXD2 or DSR1.\n");
			sysprintf("             Set JP4 to select RXD4 or CDn1.\n");
			sysprintf("             On NUC920 (UART0~2) EV board, none.\n");
			sysprintf("             On NUC960 (UART0~2) EV board, none.\n");
			sysprintf("Test Result: Porgram should print the test message.\n");		
			break;
			
		case 3:
			sysprintf("\n");
			sysprintf("Description: Get UART register value.\n");
			sysprintf("Test   Tool: None.\n");			
			sysprintf("H/W Setting: On NUC910 (UART0~4) EV board, set JP1 to select TXD2 or DTR1.\n");
			sysprintf("             Set JP2 to select TXD4 or RIn1. set JP3 to select RXD2 or DSR1.\n");
			sysprintf("             Set JP4 to select RXD4 or CDn1.\n");
			sysprintf("             On NUC920 (UART0~2) EV board, none.\n");
			sysprintf("             On NUC960 (UART0~2) EV board, none.\n");
			sysprintf("Test Result: Porgram should print the test message.\n");		
			break;
			
		case 4:
			sysprintf("\n");
			sysprintf("Description: UART line status interrupt test. Plug in the RS232 socket that\n");
			sysprintf("             TX/RX closed.\n");
			sysprintf("Test   Tool: RS232 socket.\n");			
			sysprintf("H/W Setting: On NUC910 (UART0~4) EV board, set JP1 to select TXD2 or DTR1.\n");
			sysprintf("             Set JP2 to select TXD4 or RIn1. set JP3 to select RXD2 or DSR1.\n");
			sysprintf("             Set JP4 to select RXD4 or CDn1.\n");
			sysprintf("             On NUC920 (UART0~2) EV board, none.\n");
			sysprintf("             On NUC960 (UART0~2) EV board, none.\n");
			sysprintf("Test Result: Porgram should print the test message.\n");		
			break;		
			
		case 5:
			sysprintf("\n");
			sysprintf("Description: Modem loopback test.\n");
			sysprintf("Test   Tool: None.\n");			
			sysprintf("H/W Setting: On NUC910 (UART0~4) EV board, set JP1 to select TXD2 or DTR1.\n");
			sysprintf("             Set JP2 to select TXD4 or RIn1. set JP3 to select RXD2 or DSR1.\n");
			sysprintf("             Set JP4 to select RXD4 or CDn1.\n");
			sysprintf("             On NUC920 (UART0~2) EV board, none.\n");
			sysprintf("             On NUC960 (UART0~2) EV board, none.\n");
			sysprintf("Test Result: Porgram should print the test message.\n");		
			break;	
			
		case 6:
			sysprintf("\n");
			sysprintf("Description: UART1 High speed test. If test with Bluetooth module, program\n");
			sysprintf("             should delay the TX process. If test with hyperterminal, pay\n");
			sysprintf("             attention to RS232 transceiver limitation.\n");
			sysprintf("             First, set hyperterminal to capture text and start TX test.\n");
			sysprintf("             Second, start RX test and send the text file by hyperterminal.\n");
			sysprintf("             Program will compare the TX & RX data.\n");
			sysprintf("Test   Tool: Bluetooth module or hyperterminal.\n");			
			sysprintf("H/W Setting: On NUC910 (UART0~4) EV board, set JP1 to select TXD2 or DTR1.\n");
			sysprintf("             Set JP2 to select TXD4 or RIn1. set JP3 to select RXD2 or DSR1.\n");
			sysprintf("             Set JP4 to select RXD4 or CDn1.\n");
			sysprintf("             On NUC920 (UART0~2) EV board, none.\n");
			sysprintf("             On NUC960 (UART0~2) EV board, none.\n");
			sysprintf("Test Result: Porgram should print the test message.\n");		
			break;	
			
		case 7:
			sysprintf("\n");
			sysprintf("Description: UART2 IrDA test.\n");
			sysprintf("             First, set hyperterminal to capture text and start TX test.\n");
			sysprintf("             Second, start RX test and send the text file by hyperterminal.\n");
			sysprintf("             Program will compare the TX & RX data.\n");
			sysprintf("Test   Tool: IrDA module.\n");			
			sysprintf("H/W Setting: On NUC910 (UART0~4) EV board, set JP1 to select TXD2 or DTR1.\n");
			sysprintf("             Set JP2 to select TXD4 or RIn1. set JP3 to select RXD2 or DSR1.\n");
			sysprintf("             Set JP4 to select RXD4 or CDn1.\n");
			sysprintf("             On NUC920 (UART0~2) EV board, none.\n");
			sysprintf("             On NUC960 (UART0~2) EV board, none.\n");
			sysprintf("Test Result: Porgram should print the test message.\n");		
			break;	
			
		case 8:
			sysprintf("\n");
			sysprintf("Description: Modem test.\n");
			sysprintf("Test   Tool: Real modem.\n");			
			sysprintf("H/W Setting: On NUC910 (UART0~4) EV board, set JP1 to select TXD2 or DTR1.\n");
			sysprintf("             Set JP2 to select TXD4 or RIn1. set JP3 to select RXD2 or DSR1.\n");
			sysprintf("             Set JP4 to select RXD4 or CDn1.\n");
			sysprintf("             On NUC920 (UART0~2) EV board, none.\n");
			sysprintf("             On NUC960 (UART0~2) EV board, none.\n");
			sysprintf("Test Result: Porgram should print the test message.\n");		
			break;	
			
		case 12:
			sysprintf("\n");
			sysprintf("Description: UART1 H/W flow control test. Select hardware flow control of\n");
			sysprintf("             hyperterminal.\n");
			sysprintf("             First, set hyperterminal to capture text and start TX test.\n");
			sysprintf("             Second, start RX test and send the text file by hyperterminal.\n");
			sysprintf("             Program will compare the TX & RX data.\n");
			sysprintf("Test   Tool: Hyperterminal.\n");			
			sysprintf("H/W Setting: On NUC910 (UART0~4) EV board, set JP1 to select TXD2 or DTR1.\n");
			sysprintf("             Set JP2 to select TXD4 or RIn1. set JP3 to select RXD2 or DSR1.\n");
			sysprintf("             Set JP4 to select RXD4 or CDn1.\n");
			sysprintf("             On NUC920 (UART0~2) EV board, none.\n");
			sysprintf("             On NUC960 (UART0~2) EV board, none.\n");
			sysprintf("Test Result: Porgram should print the test message.\n");		
			break;		
			
		case 13:
			sysprintf("\n");
			sysprintf("Description: UART1 S/W flow control test. Select Xon/Xoff control of\n");
			sysprintf("             hyperterminal.\n");
			sysprintf("             First, set hyperterminal to capture text and start TX test.\n");
			sysprintf("             Second, start RX test and send the text file by hyperterminal.\n");
			sysprintf("             Program will compare the TX & RX data.\n");
			sysprintf("Test   Tool: Hyperterminal.\n");			
			sysprintf("H/W Setting: On NUC910 (UART0~4) EV board, set JP1 to select TXD2 or DTR1.\n");
			sysprintf("             Set JP2 to select TXD4 or RIn1. set JP3 to select RXD2 or DSR1.\n");
			sysprintf("             Set JP4 to select RXD4 or CDn1.\n");
			sysprintf("             On NUC920 (UART0~2) EV board, none.\n");
			sysprintf("             On NUC960 (UART0~2) EV board, none.\n");
			sysprintf("Test Result: Porgram should print the test message.\n");		
			break;												
		
		default:
			break;
	}
	
	sysprintf("\nAny key start test ...\n");
	ch = sysGetChar();	
}
// HHWu adde

static VOID _UART_ShowErrInfo(INT errno) 
{
	UINT32 err = 0;
	
	switch(errno)
	{
		case 0:
			sysprintf("\nSuccess\n");	
			break;		
		case UART_ENOTTY:
			sysprintf("\nCommand not support\n");	
			break;						
		case UART_ENODEV:	
			sysprintf("\nUART channel number out of range\n");	
			break;			
		case UART_EIO:		
			sysprintf("\nRead or Write error\n");	
			break;
	
		default:
			sysprintf("\nReturn value [%d]\n\n", errno);	return;
	}	

	/* Get more detail error information */
	uartIoctl(param.ucUartNo, UART_IOC_GETERRNO, (UINT32) &err, 0);
	sysprintf("UART driver error number [%d]\n", err);
}	

static VOID _UART_SetChannel(VOID)
{
	INT ch;
	
	while(1)
	{
		sysprintf("\nSelect UART channel: \n");
		sysprintf("+------------------------+\n");
		sysprintf("| UART channel 1   - [1] |\n");
		sysprintf("| UART channel 2   - [2] |\n");
		sysprintf("| UART channel 3   - [3] |\n");
		sysprintf("| UART channel 4   - [4] |\n");
		sysprintf("+------------------------+\n");	
		ch = sysGetChar();
		if ( (ch >= '1') && (ch <= '4') )
		{
			param.ucUartNo = ch - 0x30;
			break;	
		}
	}	
}	

static VOID _UART_SetFrequency(VOID)
{
	sysprintf("\nSet UART frequency as 15MHz: \n");
	param.uFreq = 15000000;	
}	

static VOID _UART_SetBaudrate(VOID)
{
	INT ch;
	
	while(1)
	{
		sysprintf("\nSelect UART baudrate: \n");
		sysprintf("+-----------------------------+\n");
		sysprintf("| 9600                  - [0] |\n");	
		sysprintf("| 19200                 - [1] |\n");
		sysprintf("| 38400                 - [2] |\n");
		sysprintf("| 57600                 - [3] |\n");
		sysprintf("| 115200                - [4] |\n");
		sysprintf("+-----------------------------+\n");		
		ch = sysGetChar();
		if ( (ch >= '0') && (ch <= '4') )
		{
			switch(ch) 
			{
				case '0':	
					param.uBaudRate = 9600;    
					break;
				case '1':	
					param.uBaudRate = 19200;   
					break;
				case '2':	
					param.uBaudRate = 38400;   
					break;
				case '3':   
					param.uBaudRate = 57600;   
					break;
				case '4':	
					param.uBaudRate = 115200;  
					break;
				
				default:	
					break;
			}
			break;	
		}
	}
}	

static VOID _UART_SetDataBit(VOID)
{
	INT ch;
	
	while(1)
	{
		sysprintf("\nSelect UART data bit: \n");
		sysprintf("+---------------------------+\n");
		sysprintf("| 5 bits              - [0] |\n");	
		sysprintf("| 6 bits              - [1] |\n");
		sysprintf("| 7 bits              - [2] |\n");
		sysprintf("| 8 bits              - [3] |\n");
		sysprintf("+---------------------------+\n");
		ch = sysGetChar();
		if ( (ch >= '0') && (ch <= '3') )
		{
			switch(ch) 
			{
				case '0':	
					param.ucDataBits = DATA_BITS_5;    
					break;
				case '1':	
					param.ucDataBits = DATA_BITS_6;   
					break;
				case '2':	
					param.ucDataBits = DATA_BITS_7;   
					break;
				case '3':  
					param.ucDataBits = DATA_BITS_8;   
					break;
				
				default:	
					break;
			}
			break;		
		}
	}	
}	

static VOID _UART_SetStopBit(VOID)
{
	INT ch;
	
	while(1)
	{
		sysprintf("\nSelect UART stop bit: \n");
		sysprintf("+---------------------------+\n");
		sysprintf("| 1 stop bits         - [0] |\n");	
		sysprintf("| 1.5 or 2 stop bits  - [1] |\n");
		sysprintf("+---------------------------+\n");		
		ch = sysGetChar();
		if ( (ch >= '0') && (ch <= '1') )
		{
			switch(ch) 
			{
				case '0':	
					param.ucStopBits = STOP_BITS_1;    
					break;				
				case '1':	
					param.ucStopBits = STOP_BITS_2;   
					break;
				
				default:	
					break;
			}
			break;			
		}
	}		
}	

static VOID _UART_SetParity(VOID)
{
	INT ch;
	
	while(1)
	{
		sysprintf("\nSelect UART parity: \n");
		sysprintf("+---------------------------+\n");
		sysprintf("| None parity         - [0] |\n");	
		sysprintf("| Odd parity          - [1] |\n");
		sysprintf("| Even parity         - [2] |\n");
		sysprintf("+---------------------------+\n");		
		ch = sysGetChar();
		if ( (ch >= '0') && (ch <= '2') )
		{
			switch(ch) 
			{
				case '0':	
					param.ucParity = PARITY_NONE;    
					break;
				case '1':	
					param.ucParity = PARITY_ODD;   
					break;
				case '2':	
					param.ucParity = PARITY_EVEN;   
					break;
				
				default:	
					break;
			}
			
			if ( (ch == '1') || (ch == '2') )
			{
				sysprintf("\nDo you want to set stick parity? [y/n]\n");
				ch = sysGetChar();
				if ( (ch == 'y') || (ch == 'Y') )
					param.ucParity |= PARITY_STICK;
			}			
			break;	
		}
	}		
}	

static VOID _UART_SetTriggerLevel(INT nNum)
{
	INT ch;
	
	while(1)
	{
		if (nNum == UART1)
		{
			sysprintf("\nSelect UART1 RX trigger level: \n");
			sysprintf("+---------------------------+\n");
			sysprintf("| 1 byte              - [0] |\n");	
			sysprintf("| 4 bytes             - [1] |\n");
			sysprintf("| 8 bytes             - [2] |\n");
			sysprintf("| 14 bytes            - [3] |\n");
			sysprintf("| 30 bytes            - [4] |\n");
			sysprintf("| 46 bytes            - [5] |\n");
			sysprintf("| 62 bytes            - [6] |\n");
			sysprintf("+---------------------------+\n");
			ch = sysGetChar();
			if ( (ch < '0') || (ch > '6') )
				continue;
		
			switch(ch) 
			{
				case '0':	
					param.ucRxTriggerLevel = UART1_LEVEL_1_BYTE;    
					break;
				case '1':	
					param.ucRxTriggerLevel = UART1_LEVEL_4_BYTES;    
					break;
				case '2':	
					param.ucRxTriggerLevel = UART1_LEVEL_8_BYTES;    
					break;
				case '3':   
					param.ucRxTriggerLevel = UART1_LEVEL_14_BYTES;   
					break;
				case '4':   
					param.ucRxTriggerLevel = UART1_LEVEL_30_BYTES;   
					break;
				case '5':   
					param.ucRxTriggerLevel = UART1_LEVEL_46_BYTES;   
					break;
				case '6':   
					param.ucRxTriggerLevel = UART1_LEVEL_62_BYTES;   
					break;			
					
				default:	
					break;
			}			
			break;	
		}
		else
		{
			sysprintf("\nSelect RX trigger level: \n");
			sysprintf("+---------------------------+\n");
			sysprintf("| 1 byte              - [0] |\n");	
			sysprintf("| 4 bytes             - [1] |\n");
			sysprintf("| 8 bytes             - [2] |\n");
			sysprintf("| 14 bytes            - [3] |\n");
			sysprintf("+---------------------------+\n");
			ch = sysGetChar();
			if ( (ch >= '0') && (ch <= '3') )
			{
				switch(ch) 
				{
					case '0':	
						param.ucRxTriggerLevel = LEVEL_1_BYTE;    
						break;
					case '1':	
						param.ucRxTriggerLevel = LEVEL_4_BYTES;    
						break;
					case '2':	
						param.ucRxTriggerLevel = LEVEL_8_BYTES;    
						break;
					case '3':   
						param.ucRxTriggerLevel = LEVEL_14_BYTES;   
						break;
						
					default:	
						break;
				}			
				break;	
			}
		}
	}  /* End of while loop */	
}	

static VOID _UART_ConfigureUart(INT nNum)
{
	if(nNum == ALLCHANNEL)
	{
		/* UART channel */
		_UART_SetChannel();
	}
	else
		param.ucUartNo = nNum;	
	
	/* UART frequency */
	_UART_SetFrequency();
	
	/* UART baudrate */
	_UART_SetBaudrate();
		
	/* UART data bit */	
	_UART_SetDataBit();

	/* UART stop bit */	
	_UART_SetStopBit();
	
	/* UART parity */
	_UART_SetParity();
	
	/* UART RX trigger level */
	_UART_SetTriggerLevel(param.ucUartNo);
}	

/*-----------------------------------------------------------------------------------*/
/* Function:                                                                         */
/*   UART_RX                                                                         */
/*                                                                                   */
/* Parameters:                                                                       */
/*   None.                                                                           */
/*                                                                                   */                                                                           
/* Returns:                                                                          */
/*  rtval		Return the received character length.                                */
/*				Or return 0xFFFF1702 or 0xFFFF1703, uartRead() failed.               */
/*                                                                                   */
/* Side effects:                                                                     */
/*   None.                                                                           */
/*                                                                                   */
/* Description:                                                                      */
/*   Support both interrupt mode and polling mode of UART RX.                        */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/

static INT UART_RX(VOID)
{
	INT ch, rtval, err = 0, cnt = 0;
	
	/* Configure UART */
	sysprintf("\n Configure UART manually or not [y/n]\n");
	ch = sysGetChar();
	if (ch == 'y')
		_UART_ConfigureUart(ALLCHANNEL);
	else
	{
		param.uFreq = 15000000;
		param.uBaudRate = comBaudRate[3];  /* 115200 bps */
		param.ucUartNo = UART1;
		param.ucDataBits = DATA_BITS_8;
		param.ucStopBits = STOP_BITS_1;
		param.ucParity = PARITY_NONE;
		if (param.ucUartNo == UART1)
			param.ucRxTriggerLevel = UART1_LEVEL_1_BYTE;
		else
			param.ucRxTriggerLevel = LEVEL_1_BYTE;	
	}	
		
	rtval = uartOpen(&param); 
	if(rtval != 0) 
	{
		_UART_ShowErrInfo(rtval);
		return (rtval);
	}	
	
	while(1)
	{
		/* Select Rx interrupt or polling test */
		sysprintf("\n Select Rx interrupt/polling mode[0/1]\n");
		ch = sysGetChar();
		if((ch != '1') && (ch != '0')) 
			continue;
		else	
			break;	
	}		
			
	if(ch == '0')
	{
		sysprintf(" Interrupt mode selected\n");
		rtval = uartIoctl(param.ucUartNo, UART_IOC_SETRXMODE, UARTINTMODE, 0);	
	}
	else
	{ 
		sysprintf(" Polling mode selected\n");
		rtval = uartIoctl(param.ucUartNo, UART_IOC_SETRXMODE, UARTPOLLMODE, 0);	
	}
		
	if(rtval != 0) 
	{
		_UART_ShowErrInfo(rtval);
		err = 1;
		goto error;
	}

	/* Start Rx test */
	sysprintf("\nKeyin 10 char from UART channel[%d] by HyperTerminal\n", param.ucUartNo);			
	cnt = 0;
	while(1)
	{
		rtval = uartRead(param.ucUartNo, RX_Test, 1);
		if(rtval > 0) 
		{
			sysprintf("%d[0x%x]\n", cnt + 1, RX_Test[0]);
			cnt++;
			if (cnt >= 10)
				break;
		}
	}			

error:

	uartRelease(param.ucUartNo);
	
	if(err)	
		return (rtval);
		
	return 0;	
}	

/*-----------------------------------------------------------------------------------*/
/* Function:                                                                         */
/*   UART_TX                                                                         */
/*                                                                                   */
/* Parameters:                                                                       */
/*   None.                                                                           */
/*                                                                                   */                                                                           
/* Returns:                                                                          */
/*  rtval		Return the transmitted character length.                             */
/*				Or return 0xFFFF1702 or 0xFFFF1703, uartRead() failed.               */
/*                                                                                   */
/* Side effects:                                                                     */
/*   None.                                                                           */
/*                                                                                   */
/* Description:                                                                      */
/*   Support both interrupt mode and polling mode of UART TX.                        */
/*                                                                                   */
/* Remark:                                                                           */
/*   1. Don't call uartRelease() at the end of this program. The TX data maybe       */
/*      not transmit completely.                                                     */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/

static INT UART_TX(VOID)
{
	INT ch, rtval, i, err = 0;
	UINT32 len;  
	
	/* Configure UART */
	sysprintf("\n Configure UART manually or not [y/n]\n");
	ch = sysGetChar();
	if (ch == 'y')
		_UART_ConfigureUart(ALLCHANNEL);
	else
	{
		param.uFreq = 15000000;
		param.uBaudRate = comBaudRate[3];  /* 115200 bps */
		param.ucUartNo = UART1;
		param.ucDataBits = DATA_BITS_8;
		param.ucStopBits = STOP_BITS_1;
		param.ucParity = PARITY_NONE;
		if (param.ucUartNo == UART1)
			param.ucRxTriggerLevel = UART1_LEVEL_1_BYTE;
		else
			param.ucRxTriggerLevel = LEVEL_1_BYTE;	
	}	
	
	rtval = uartOpen(&param); 
	if(rtval != 0) 
	{
		_UART_ShowErrInfo(rtval);
		return (rtval);
	}	
	
	while(1)
	{
		/* Select Tx interrupt or polling test */
		sysprintf("\n Select Tx interrupt/polling mode[0/1]\n");
		ch = sysGetChar();
		if((ch != '1') && (ch != '0')) 
			continue;
		else	
			break;	
	}
	
	if(ch == '0')
	{
		sysprintf(" Interrupt mode selected\n");
		rtval = uartIoctl(param.ucUartNo, UART_IOC_SETTXMODE, UARTINTMODE, 0);	
	}
	else
	{ 
		sysprintf(" Polling mode selected\n");
		rtval = uartIoctl(param.ucUartNo, UART_IOC_SETTXMODE, UARTPOLLMODE, 0);	
	}
	
	if(rtval != 0) 
	{
		_UART_ShowErrInfo(rtval);
		err = 1;
		goto error;
	}
	
	/* Start Tx test */
	sysprintf("\n Any key start to test\n");
	ch = sysGetChar();
		
	len = strlen((PINT8) TX_Test);
	for (i = 0; i < TXCNT; i++)
	{
		rtval = uartWrite(param.ucUartNo, TX_Test, len);
		if(rtval < 0)
		{
			_UART_ShowErrInfo(rtval);
			err = 1;
			goto error;
		}
	}
	
error:

	if(err)
	{
		sysprintf(" Tx test fail! [0x%08x]\n", rtval);
		return (rtval);
	}	
		
	return 0;	
}	

/*-----------------------------------------------------------------------------------*/
/* Function:                                                                         */
/*   UART_GetRegister                                                                */
/*                                                                                   */
/* Parameters:                                                                       */
/*   None.                                                                           */
/*                                                                                   */                                                                           
/* Returns:                                                                          */
/*   None.                                                                           */
/*                                                                                   */
/* Side effects:                                                                     */
/*   None.                                                                           */
/*                                                                                   */
/* Description:                                                                      */
/*   Get UART register values with UART_REGISTER_STRUCT{}.                           */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/

static VOID UART_GetRegister(VOID) 
{
	INT ch, rtval, i;
	
	UART_REGISTER_T reg;
	
	while(1)
	{
		sysprintf("\nSelect UART channel: \n");
		sysprintf("+------------------------+\n");
		sysprintf("| UART channel 0   - [0] |\n");
		sysprintf("| UART channel 1   - [1] |\n");
		sysprintf("| UART channel 2   - [2] |\n");
		sysprintf("| UART channel 3   - [3] |\n");
		sysprintf("| UART channel 4   - [4] |\n");
		sysprintf("+------------------------+\n");	
		ch = sysGetChar();
		if((ch < '0') || (ch > '4')) 
			continue;
		
		rtval = uartIoctl(ch - 0x30, UART_IOC_GETUARTREGISTERVALUE, (UINT32)&reg, 0);		
		if(rtval <= 0)
			_UART_ShowErrInfo(rtval);  
		else
		{
			for(i = 0; i < rtval; i++)
				sysprintf("\n[0x%x] = 0x%x", reg.uUartReg[i][0], reg.uUartReg[i][1]);
		}	
		
		sysprintf("\n\n  Continue this test item [y/n]\n");
		ch = sysGetChar();
		if((ch == 'n') || (ch == 'N'))
			break;
	}	
}	 

/*-----------------------------------------------------------------------------------*/
/* Function:                                                                         */
/*   UART_Line_Break                                                                 */
/*                                                                                   */
/* Parameters:                                                                       */
/*   None.                                                                           */
/*                                                                                   */                                                                           
/* Returns:                                                                          */
/*   None.                                                                           */
/*                                                                                   */
/* Side effects:                                                                     */
/*   None.                                                                           */
/*                                                                                   */
/* Description:                                                                      */
/*   Note that don't enable Receive Line Status Interrupt ordinarily.                */
/*	 The Rx function will be effected. This program should be tested like            */
/*   UART_Loopback(), exteranl loopback test.                                        */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/

static VOID UART_Line_Break(VOID) 
{
	INT ch, rtval;
	UINT32 uBIIState;
	
	while(1)
	{
		/* Select UART channel */
		sysprintf("\n Select UART channel [1~4]\n");
		ch = sysGetChar();
		if((ch < '1') || (ch > '4')) 
			continue;
		
		/* configure UART */
		param.uFreq = 15000000;
		param.uBaudRate = 115200;
		param.ucUartNo = ch - 0x30;
		param.ucDataBits = DATA_BITS_8;
		param.ucStopBits = STOP_BITS_1;
		param.ucParity = PARITY_NONE;
		if (param.ucUartNo == UART1)
			param.ucRxTriggerLevel = UART1_LEVEL_1_BYTE;
		else
			param.ucRxTriggerLevel = LEVEL_1_BYTE;		
		
		rtval = uartOpen(&param); 
		if(rtval != 0) 
		{
			_UART_ShowErrInfo(rtval);
			return;
		}
		
		/* enable Break Control bit */
		uartIoctl(param.ucUartNo, UART_IOC_SETBREAKCONTROL, 1, 0);	
		
		/* Note that don't enable Receive Line Status interrupt ordinarily */
		uartIoctl(param.ucUartNo, UART_IOC_SETINTERRUPT, 1, IER_RLS);	
		
		/* TX, one char */
		rtval = uartWrite(param.ucUartNo, &TX_Test_LB[0], 1);
		if(rtval < 0) 
		{
			_UART_ShowErrInfo(rtval);
			return;
		}
		
		while(1)
		{
			/* get BII state */
			uartIoctl(param.ucUartNo, UART_IOC_GETBIISTATE, (UINT32) &uBIIState, 0);
			if(uBIIState == 1)	
			{
				sysprintf("\nUART channel [%d] break interrupt test ok\n", param.ucUartNo);
				uBIIState = 0;
				break;	
			}	
		}	
		
		/* disable Receive Line Status interrupt */
		uartIoctl(param.ucUartNo, UART_IOC_SETINTERRUPT, 0, IER_RLS);	
		
		/* disable Break Control bit */
		uartIoctl(param.ucUartNo, UART_IOC_SETBREAKCONTROL, 0, 0);	
		
		sysprintf("\n Continue this test item [y/n]\n");
		ch = sysGetChar();
		if((ch == 'n') || (ch == 'N'))
			break;	
		
	}  // end of while loop		
} 	

/*-----------------------------------------------------------------------------------*/
/* Function:                                                                         */
/*   UART_Modem_Loopback                                                             */
/*                                                                                   */
/* Parameters:                                                                       */
/*   None.                                                                           */
/*                                                                                   */                                                                           
/* Returns:                                                                          */
/*   None.                                                                           */
/*                                                                                   */
/* Side effects:                                                                     */
/*   None.                                                                           */
/*                                                                                   */
/* Description:                                                                      */
/*   Use modem loopback function to test modem interrupt occured and RTS/CTS         */
/*   DTR/DSR pin.                                                                    */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/

static VOID UART_Modem_Loopback(VOID) 
{
	UINT32 uDSRState = 0, uDSRVal = 0, uCTSState = 0, uCTSVal = 0, rtval, ch, i;
	
	//sysprintf("Make sure the H/W configuration of different UART channel!\n");
	while(1)
	{
		sysprintf("\n Select UART channel [1/3]\n");
		ch = sysGetChar();
		if( (ch != '1') && (ch != '3') )
			continue;
		
		/* configure UART */
		param.uFreq = 15000000;
		param.uBaudRate = 115200;
		param.ucUartNo = ch - 0x30;  /* only UART1 & UART3 */
		param.ucDataBits = DATA_BITS_8;
		param.ucStopBits = STOP_BITS_1;
		param.ucParity = PARITY_NONE;
		if (param.ucUartNo == UART1)
			param.ucRxTriggerLevel = UART1_LEVEL_1_BYTE;
		else	
			param.ucRxTriggerLevel = LEVEL_1_BYTE;
		
		rtval = uartOpen(&param); 
		if(rtval != 0) 
		{
			_UART_ShowErrInfo(rtval);
			return;
		}
		
		/* 
			UART1, full modem must call ioctl UART_IOC_SETUART1FULLMODEM.
			Note that UART2 & UART4 will change the GPIO settings as UART1 full modem pins.
			
			UART3, DTR & DSR.
		*/
		if (ch == '1')
		{
			rtval = uartIoctl(UART1, UART_IOC_SETUART1FULLMODEM, 0, 0);  
			if(rtval != 0) 
			{
				_UART_ShowErrInfo(rtval);
				return;	
			}
		}
		
		/* enable modem interrupt */
		uartIoctl(param.ucUartNo, UART_IOC_SETMODEMINTERRUPT, UART_ENABLE_MODEM_INT, 0);
		
		/* enable modem loopback */
		uartIoctl(param.ucUartNo, UART_IOC_SETMODEMLOOPBACK, UART_ENABLE_LOOPBACK, 0);
		
		uDSRState = uDSRVal = uCTSState = uCTSVal = 0;
		if(param.ucUartNo == UART1)  
		{
			/*
				UART1: Test CTS(In) RTS(Out) DSR(In) DTR(Out). Enable loop-back mode, DTR 
				       fixed at logic 1 and RTS fixed at logic 1.
			*/	
			
			/* 1. set DTR, RTS low */
			uartIoctl(UART1, UART_IOC_SETDTRSIGNAL, UART_DTR_LOW, 0);
			uartIoctl(UART1, UART_IOC_SETRTSSIGNAL, UART_RTS_LOW, 0);			
			
			/* 2. get DSR, CTS status */
			while(1) 
			{
				uartIoctl(UART1, UART_IOC_GETDSRSTATE, (UINT32) &uDSRState, (UINT32) &uDSRVal);
				uartIoctl(UART1, UART_IOC_GETCTSSTATE, (UINT32) &uCTSState, (UINT32) &uCTSVal);		
				if( (uDSRState == 1) && (uCTSState == 1) ) 
				{  
					/* modem interrupt occured, DSR state change (high -> low) */
					if( (uDSRVal == 1) && (uCTSVal == 1) )
						sysprintf(" DSR & CTS test pass\n");
					else
						sysprintf(" DSR & CTS test fail\n");
					break;
				}			
			}
			
			/* 3. set DTR, RTS high */
			uartIoctl(UART1, UART_IOC_SETDTRSIGNAL, UART_DTR_HIGH, 0);
			uartIoctl(UART1, UART_IOC_SETRTSSIGNAL, UART_RTS_HIGH, 0);			
			
			/* 4. get DSR, CTS status */
			while(1) 
			{
				uartIoctl(UART1, UART_IOC_GETDSRSTATE, (UINT32) &uDSRState, (UINT32) &uDSRVal);
				uartIoctl(UART1, UART_IOC_GETCTSSTATE, (UINT32) &uCTSState, (UINT32) &uCTSVal);		
				if( (uDSRState == 1) && (uCTSState == 1) ) 
				{  
					/* modem interrupt occured, DSR state change (low -> high) */
					if( (uDSRVal == 0) && (uCTSVal == 0) )
						sysprintf(" DSR & CTS test pass\n");
					else
						sysprintf(" DSR & CTS test fail\n");
					break;
				}				
			}
		}
		else
		{
			/*
				UART3: Test DSR(In) DTR(Out). Enable loop-back mode, DTR fixed at logic 1.
			*/
			
			/* 1. set DTR low */
			uartIoctl(UART3, UART_IOC_SETDTRSIGNAL, UART_DTR_LOW, 0);			
			
			/* 2. get DSR status */
			while(1) 
			{
				uartIoctl(UART3, UART_IOC_GETDSRSTATE, (UINT32) &uDSRState, (UINT32) &uDSRVal);	
				if(uDSRState == 1) 
				{  
					/* modem interrupt occured, DSR state change (high -> low) */
					if(uDSRVal == 1)
						sysprintf(" DSR item 1 pass\n");
					else
						sysprintf(" DSR item 1 fail\n");	
					break;
				}			
			}
			
			/* 3. set DTR high */
			uartIoctl(UART3, UART_IOC_SETDTRSIGNAL, UART_DTR_HIGH, 0);			
			
			/* 4. get DSR status */
			while(1) 
			{
				uartIoctl(UART3, UART_IOC_GETDSRSTATE, (UINT32) &uDSRState, (UINT32) &uDSRVal);	
				if(uDSRState == 1) 
				{  
					/* modem interrupt occured, DSR state change (low -> high) */
					if(uDSRVal == 0)
						sysprintf(" DSR item 2 pass\n");
					else
						sysprintf(" DSR item 2 fail\n");	
					break;
				}			
			}
			
			/* 5. set DTR high again, modem interrupt shouldn't occured */
			uartIoctl(UART3, UART_IOC_SETDTRSIGNAL, UART_DTR_HIGH, 0);	
			for(i = 0 ; i < 1000 ; i++); 
			uartIoctl(UART3, UART_IOC_GETDSRSTATE, (UINT32) &uDSRState, (UINT32) &uDSRVal);	
			if( (uDSRState == 0) && (uDSRVal == 0) )
				sysprintf(" DSR item 3 pass\n");
			else
				sysprintf(" DSR item 3 fail\n");	
		}
		
		sysprintf("\n Continue this test item [y/n]\n");
		ch = sysGetChar();
		if((ch == 'n') || (ch == 'N'))
			break;
	}
	
	// disable modem interrupt & loopback function
	uartIoctl(param.ucUartNo, UART_IOC_SETMODEMINTERRUPT, UART_DISABLE_MODEM_INT, 0);
	uartIoctl(param.ucUartNo, UART_IOC_SETMODEMLOOPBACK, UART_DISABLE_LOOPBACK, 0);
	
#if 0  // .....	
	// test after disable modem interrupt & loopback function
	uartIoctl(param.ucUartNo, UART_IOC_SETDTRSIGNAL, UART_DTR_LOW, 0);	
	for(i = 0 ; i < 1000 ; i++);  // delay
	uartIoctl(param.ucUartNo, UART_IOC_GETDSRSTATE, (UINT32) &uDSRState, (UINT32) &uDSRVal);
	if( (uDSRState != 1) && (uDSRVal != 1) )	
		sysprintf(" Finial test ok!\n");
	else
		sysprintf(" Finial test fail! DSR INT[%d] Val[%d]\n", uDSRState, uDSRVal);	
#endif		
}

/*-----------------------------------------------------------------------------------*/
/* Function:                                                                         */
/*   UART_High_Speed                                                                 */
/*                                                                                   */
/* Parameters:                                                                       */
/*   None.                                                                           */
/*                                                                                   */                                                                           
/* Returns:                                                                          */
/*   None.                                                                           */
/*                                                                                   */
/* Side effects:                                                                     */
/*   None.                                                                           */
/*                                                                                   */
/* Description:                                                                      */
/*   Configure high speed UART for Bluetooth application. Test 10Kbyte data.         */
/*                                                                                   */
/* Remark:                                                                           */
/*   1. Test on Max. baud rate (6250000bps). Configure cache on and increase RX      */
/*      buffer size that test ok. If don't increase RX buffer, it will be full and   */
/*      occurr RX FIFO overrun. If configure cache off, RX FIFO overrun is still     */
/*      occurred.                                                                    */
/*   2. NUC960 don't have PLL1.                                                     */
/*   3. Test with Bluetooth moduel at 1382400bps, configure PLL0 (param.uFreq) as    */
/*      66 or 200 MHz. And delay for each 1k data transferred.                       */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/

//#define MANUALTEST
#define HIGHSPEEDSIZE	(10 * 1024)
static VOID UART_High_Speed(VOID) 
{
	int retval, ch, i, cnt, j;
	
	UINT8 tx_data[HIGHSPEEDSIZE] = {0}, rx_data[HIGHSPEEDSIZE] = {0};
	
#if 0 
	WB_PLL_T sysClock;
	
	/* Set clock control for high speed testing */
	sysClock.pll0 = PLL_200MHZ;  
	sysClock.pll1 = PLL_100MHZ;
	sysClock.cpu_src = CPU_FROM_PLL0;
	sysClock.ahb_clk = AHB_CPUCLK_1_2;
	sysClock.apb_clk = APB_AHB_1_2;	
	sysSetPLLConfig(&sysClock);

	sysDisableCache();
	sysInvalidCache();
	sysEnableCache(CACHE_WRITE_THROUGH); 
	sysprintf("\n Cache on ...\n");	
#endif	
		
	/* configure UART1 */
	param.uFreq = 100000000;      /* Take care frequency      */ 
	param.uBaudRate = 460800;   /* Max: 6250000bps (200MHz) */
	param.ucUartNo = UART1;      /* Only UART1               */
	param.ucDataBits = DATA_BITS_8;
	param.ucStopBits = STOP_BITS_1;
	param.ucParity = PARITY_NONE;
	param.ucRxTriggerLevel = UART1_LEVEL_1_BYTE;  // UART1_LEVEL_1_BYTE UART1_LEVEL_46_BYTES
	retval = uartOpen(&param); 
	if (retval != 0) 
	{
		_UART_ShowErrInfo(retval);
		return;
	}
	
	/* select the correct UART1 clock source */	
	retval = uartIoctl(UART1, UART_IOC_SETUART1HIGHSPEED, UART1_PLL1, 0);  /* Take care clock source */ 
	if (retval != 0) 
	{
		_UART_ShowErrInfo(retval);
		return;	
	}	
	
	/* Initialize TX data */
	for (i = 0; i < (HIGHSPEEDSIZE); i++)
	{
		if ( ( (i + 1) & 0xFF ) == 0x18 )  
			tx_data[i] = 0x19;
		else
			tx_data[i] = i + 1;	
	}
	
	while (1)
	{
		sysprintf("\nSelect test item TX/RX [0/1]\n");
		ch = sysGetChar();
		if ( (ch != '0') && (ch != '1') )	
			continue;
		
		if(ch == '0') 
		{
			/*
				High speed TX test
			*/
			retval = uartIoctl(param.ucUartNo, UART_IOC_SETTXMODE, UARTINTMODE, 0); /* interrupt mode */	
			if (retval != 0) 
			{
				_UART_ShowErrInfo(retval);
				return;
			}
			
			sysprintf("\n Any key start to TX test\n");
			ch = sysGetChar();
			sysprintf("\n Start TX ...\n");
			
			#ifndef MANUALTEST				
			i = 0;
			while (i < HIGHSPEEDSIZE)
			{
				retval = uartWrite(param.ucUartNo, tx_data + i, 16);  
				if (retval > 0)	
				{
					i += retval;
					//sysprintf("TX[%d]\r", i);					
					if ( (i >= 1024) && (i % 1024 == 0) )
					{
						sysprintf("delay .....\n");
						//for (j = 0; j < 0x900000; j++);  // cache on
						for (j = 0; j < 0x100000; j++);  // cache off
					}
				}
			}
			sysprintf("\nTx [%d] complete ...\n", i);	
			#else
				
			while (1)
			{
				tx_data[0] = sysGetChar();
				retval = uartWrite(param.ucUartNo, tx_data, 1);  
			}	
			
			#endif
		}
		else
		{
			/*
				High speed RX test
			*/
			
			/* interrupt mode */		
			retval = uartIoctl(param.ucUartNo, UART_IOC_SETRXMODE, UARTINTMODE, 0); 
			if(retval != 0) 
			{
				_UART_ShowErrInfo(retval);
				return;
			}
			
			/* Flush UART1 RX buffer */
			retval = uartIoctl(param.ucUartNo, UART_IOC_FLUSH_RX_BUFFER, 0, 0);  
			if(retval != 0) 
			{
				_UART_ShowErrInfo(retval);
				return;
			}
			
			memset(rx_data, 0, HIGHSPEEDSIZE);
			
			sysprintf("\n Any key start to RX test\n");
			ch = sysGetChar();
			sysprintf("\n Start RX ...\n");
			
			#ifndef MANUALTEST
			i = 0;
			while (i < HIGHSPEEDSIZE)
			{
				retval = uartRead(param.ucUartNo, rx_data + i, 200);
				if (retval > 0)	
				{
					i += retval;
					sysprintf("RX[%d]\r", i);
				}
			}
			sysprintf("\nRx [%d] complete ...\n", i);
			#else
			
			while (1)
			{
				retval = uartRead(param.ucUartNo, rx_data, 1);
				if (retval > 0)	
					sysprintf("Rx[0x%x]\r", rx_data[0]);	
			}
			
			#endif
			
			/* Compare data */	
			cnt = 0;		
			for (i = 0; i < HIGHSPEEDSIZE; i++)
			{
				if (rx_data[i] != tx_data[i])
				{
					if (cnt < 100)
						sysprintf("%d t[0x%x] r[0x%x]\n", i + 1, tx_data[i], rx_data[i]);
						
					cnt++;	
				}
			}
			
			if (cnt)
				sysprintf("compare fail [%d]!\n", cnt);
			else
				sysprintf("compare success\n");	
		}
		
		sysprintf("\n\n  Continue this test item [y/n]\n");
		ch = sysGetChar();
		if ( (ch == 'n') || (ch == 'N') )
			break;
	
	}  /* End of while loop */

}


static VOID UART_High_Speed_External_Loopback(VOID) 
{
	char Baudrate_Info[6][7] = {"9600","38400","57600","115200","230400","460800"};
	int Baudrate[6] = {9600,38400,57600,115200,230400,460800};
	int volatile stime, etime;
	int i, j, k, ch, retval, val, MaxChar;		
	UINT8 RXD, TXD;
    
    char LCR_Info[40][10] = {"N,5,1","N,5,1.5","N,6,1","N,6,2","N,7,1","N,7,2","N,8,1","N,8,2",
    						 "OP,5,1","OP,5,1.5","OP,6,1","OP,6,2","OP,7,1","OP,7,2","OP,8,1","OP,8,2",
    						 "EP,5,1","EP,5,1.5","EP,6,1","EP,6,2","EP,7,1","EP,7,2","EP,8,1","EP,8,2",
    						 "SOP,5,1","SOP,5,1.5","SOP,6,1","SOP,6,2","SOP,7,1","SOP,7,2","SOP,8,1","SOP,8,2",
    						 "SEP,5,1","SEP,5,1.5","SEP,6,1","SEP,6,2","SEP,7,1","SEP,7,2","SEP,8,1","SEP,8,2"};
	unsigned char Item_LCR[40] = {0x00,0x04,0x01,0x05,0x02,0x06,0x03,0x07,
    							  0x08,0x0C,0x09,0x0D,0x0A,0x0E,0x0B,0x0F,
    							  0x18,0x1C,0x19,0x1D,0x1A,0x1E,0x1B,0x1F,
    							  0x28,0x2C,0x29,0x2D,0x2A,0x2E,0x2B,0x2F,
    							  0x38,0x3C,0x39,0x3D,0x3A,0x3E,0x3B,0x3F};    						 

	stime = sysGetTicks(TIMER0);	
	for (i = 0; i < 6; i++)
	{
		for (j = 0; j < 40; j++)
		{
			sysprintf("%s, %s: ", Baudrate_Info[i], LCR_Info[j]);
			
			/* configure UART */
			param.uFreq = 100000000;      /* Take care frequency      */ 
			param.uBaudRate = Baudrate[i];			
			param.ucUartNo = UART1;      /* Only UART1               */
			
			val = Item_LCR[j] & 0x03;
			param.ucDataBits = val;				
			val = Item_LCR[j] & 0x04;			
			param.ucStopBits = val;			
			val = Item_LCR[j] & 0x38;	
			param.ucParity = val;			
			param.ucRxTriggerLevel = UART1_LEVEL_1_BYTE;  // UART1_LEVEL_1_BYTE UART1_LEVEL_46_BYTES

			retval = uartOpen(&param); 
			if (retval != 0) 
			{
				_UART_ShowErrInfo(retval);
				return;
			}

			/* select the correct UART1 clock source */	
			retval = uartIoctl(UART1, UART_IOC_SETUART1HIGHSPEED, UART1_PLL1, 0);  /* Take care clock source */ 
			if (retval != 0) 
			{
				_UART_ShowErrInfo(retval);
				return;	
			}	
			
			retval = uartIoctl(param.ucUartNo, UART_IOC_FLUSH_RX_BUFFER, 0, 0);  
			retval = uartIoctl(param.ucUartNo, UART_IOC_SETTXMODE, UARTINTMODE, 0);
			retval = uartIoctl(param.ucUartNo, UART_IOC_SETRXMODE, UARTINTMODE, 0);
			
			val = Item_LCR[j] & 0x03;
		    if (val == 0x00)  	   /* character length 5 bits */
		    	MaxChar = 0x20;
		    else if (val == 0x01)  /* character length 6 bits */
		    	MaxChar = 0x40;	
		    else if( val == 0x02)  /* character length 7 bits */
		    	MaxChar = 0x80;
		    else if (val == 0x03)  /* character length 8 bits */
		    	MaxChar = 0x100;	
		    	
		    stime = sysGetTicks(TIMER0);
		    for (k = 0; k < MaxChar; k++)
		    {
		    	/* start TX */
		    	TXD = k;
		    	retval = uartWrite(param.ucUartNo, &TXD, 1);
				if(retval < 0)
				{
					sysprintf("TX [0x%x] error!\n", k);
					break;
				}
				
				/* start RX, must receive data */
				while (1)
				{
					retval = uartRead(param.ucUartNo, &RXD, 1);
					if (retval < 0)
					{
						sysprintf("RX [0x%x] error!\n", k);
						break;					
					}
					else if (retval == 1)
					{
						//sysprintf("RX[0x%x]\n", RXD);
						stime = etime;
						break;	
					}
					
					etime = sysGetTicks(TIMER0);
					if (etime - stime >= 100)  /* time out 1sec */
					{
						sysprintf("\n\nRX time out!\n");
						goto EXITTEST;
					}
					
					if (inpw(REG_UART0_LSR) & 0x01)	
					{
						sysprintf("\n\nExit test!\n");
						goto EXITTEST;	
					}	
				}
				
				if (RXD != TXD)
				{
					sysprintf("Data comparison error!\n");
					break;	
				}
		    }
		    
		    if (k == MaxChar)
				sysprintf("OK\n");
			else
				sysprintf ("FAIL (outChar=%0x, inChar=%0x)!\n", TXD, RXD);				
		}		
	}

EXITTEST:
	
	uartRelease(param.ucUartNo);
	sysprintf("Close UART[%d]\n", param.ucUartNo);
	
	sysprintf("\nAny key continually ...\n");
	ch = sysGetChar();			
}





/*-----------------------------------------------------------------------------------*/
/* Function:                                                                         */
/*   UART_IrDA                                                                       */
/*                                                                                   */
/* Parameters:                                                                       */
/*   None.                                                                           */
/*                                                                                   */                                                                           
/* Returns:                                                                          */
/*   0				Success.                                                         */
/*   < 0			Fail.                                                            */
/*                                                                                   */
/* Side effects:                                                                     */
/*   None.                                                                           */
/*                                                                                   */
/* Description:                                                                      */
/*   Test both TX and RX of UART channel 2 as IrDA function.                         */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/

//#define IrDAMANUALTEST
#define IrDASIZE	(10 * 1024)  
static VOID UART_IrDA(VOID) 
{
	int i, retval, ch, cnt;
	UINT8 tx_data[IrDASIZE] = {0}, rx_data[IrDASIZE] = {0}, txflag = 0, rxflag = 0;
	
	/* configure UART2 */
	param.uFreq = 15000000;          /* 15MHz      */
	param.uBaudRate = 115200;  
	param.ucUartNo = UART2;          /* Only UART2 */
	param.ucDataBits = DATA_BITS_8;
	param.ucStopBits = STOP_BITS_1;
	param.ucParity = PARITY_NONE;
	param.ucRxTriggerLevel = LEVEL_1_BYTE;  // LEVEL_1_BYTE LEVEL_8_BYTES LEVEL_14_BYTES
	retval = uartOpen(&param); 
	if (retval != 0) 
	{
		_UART_ShowErrInfo(retval);
		return;
	}
	
	/* Initialize TX data */
	for (i = 0; i < IrDASIZE; i++)
	{
		if ( ( (i + 1) & 0xFF ) == 0x18 )  
			tx_data[i] = 0x19;
		else
			tx_data[i] = i + 1;	
	}

	while (1)
	{
		sysprintf("\nSelect test item, IrDA TX/RX [0/1]\n");
		ch = sysGetChar();
		if ( (ch != '0') && (ch != '1') )	
			continue;
		
		if (ch == '0') 
		{
			if (rxflag)
				rxflag = 0;  /* initialize flag */
			
			/*
				UART2 IrDA TX Test
			*/
			if (txflag == 0)
			{
				txflag = 1;
				sysprintf("\nTx Interrupt mode\n");
				retval = uartIoctl(param.ucUartNo, UART_IOC_SETTXMODE, UARTINTMODE, 0); /* interrupt mode */	
				if (retval != 0) 
				{
					_UART_ShowErrInfo(retval);
					return;
				}
				
				sysprintf("Enable IrDA Tx\n");
				retval = uartIoctl(UART2, UART_IOC_PERFORMIrDA, ENABLEIrDA, IrDA_TX);  /* Enable IrDA function */
				if (retval != 0) 
				{
					_UART_ShowErrInfo(retval);
					return;
				}	
			}		
			
			sysprintf("\n Any key start to TX test\n");
			ch = sysGetChar();
			sysprintf("\n Start TX ...\n");
			
			#ifndef IrDAMANUALTEST	
			i = 0;
			while (i < IrDASIZE)
			{
				retval = uartWrite(param.ucUartNo, tx_data + i, 10);  
				if (retval > 0)	
				{
					i += retval;
					//sysprintf("TX[%d]\r", i);
				}
			}
			sysprintf("\nTx [%d] complete ...\n", i);	
			#else
				
			while (1)
			{
				tx_data[0] = sysGetChar();
				retval = uartWrite(param.ucUartNo, tx_data, 1);
				if (retval > 0)
					sysprintf("Tx[0x%x]\r", tx_data[0]);	  
			}	
			
			#endif
		}
		else
		{
			if (txflag)
				txflag = 0;  /* initialize flag */
			
			/*
				UART2 IrDA RX Test
			*/
			if (rxflag == 0)
			{
				rxflag = 1;
				sysprintf("\nRx Interrupt mode\n");
				retval = uartIoctl(param.ucUartNo, UART_IOC_SETRXMODE, UARTINTMODE, 0); /* interrupt mode */		
				if(retval != 0) 
				{
					_UART_ShowErrInfo(retval);
					return;
				}
				
				sysprintf("Enable IrDA Rx\n");
				retval = uartIoctl(UART2, UART_IOC_PERFORMIrDA, ENABLEIrDA, IrDA_RX);  /* Enable IrDA function */
				if(retval != 0) 
				{
					_UART_ShowErrInfo(retval);
					return;
				}
			}
			
			retval = uartIoctl(UART2, UART_IOC_FLUSH_RX_BUFFER, 0, 0);  /* Flush UART2 RX buffer */
			if(retval != 0) 
			{
				_UART_ShowErrInfo(retval);
				return;
			}
			
			memset(rx_data, 0, IrDASIZE);
			
			sysprintf("\n Any key start to RX test\n");
			ch = sysGetChar();
			sysprintf("\n Start RX ...\n");
			
			#ifndef IrDAMANUALTEST
			i = 0;
			while (i < IrDASIZE)
			{
				retval = uartRead(param.ucUartNo, rx_data + i, 100);
				if (retval > 0)	
				{
					i += retval;
					//sysprintf("RX[%d]\r", i);
				}
			}
			sysprintf("\nRx [%d] complete ...\n", i);
			#else
			
			while (1)
			{
				retval = uartRead(param.ucUartNo, rx_data, 1);
				if (retval > 0)	
					sysprintf("Rx[0x%x]\r", rx_data[0]);	
			}
			
			#endif
			
			/* Compare data */	
			cnt = 0;		
			for (i = 0; i < IrDASIZE; i++)
			{
				if (rx_data[i] != tx_data[i])
				{
					if (cnt < 100)
						sysprintf("%d t[0x%x] r[0x%x]\n", i + 1, tx_data[i], rx_data[i]);
						
					cnt++;	
				}
			}
			
			if (cnt)
				sysprintf("compare fail [%d]!\n", cnt);
			else
				sysprintf("compare [%d] success\n", i);	
		}
		
		sysprintf("\n\n  Continue this test item [y/n]\n");
		ch = sysGetChar();
		if ( (ch == 'n') || (ch == 'N') )
			break;
	
	}  /* End of while loop */
	
	sysprintf("\n Disable IrDA\n");
	retval = uartIoctl(UART2, UART_IOC_PERFORMIrDA, DISABLEIrDA, 0);
	if(retval != 0)
		_UART_ShowErrInfo(retval);

}

/*-----------------------------------------------------------------------------------*/
/* Function:                                                                         */
/*   UART_Modem_Test                                                                 */
/*                                                                                   */
/* Parameters:                                                                       */
/*   None.                                                                           */
/*                                                                                   */                                                                           
/* Returns:                                                                          */
/*   None.                                                                           */       
/*                                                                                   */
/* Side effects:                                                                     */
/*   None.                                                                           */
/*                                                                                   */
/* Description:                                                                      */
/*   Test with modem borrow from YAChen.                                             */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/

static VOID UART_Modem_Test(VOID)
{
	unsigned char initString[] = {'A', 'T', '&', 'F' , '0' , 0x0d};
	unsigned char initString_1[] = {'A', 'T', '&', 'F' , '1' , 0x0d};
	unsigned char buf[64];
	int index, i, j, rtval, /*ch,*/ len, mflag = 0;
	
	/* Configure UART channel 1 */
	param.uFreq = 15000000;
	param.ucUartNo = UART1;
	param.ucDataBits = DATA_BITS_8;
	param.ucStopBits = STOP_BITS_1;
	param.ucParity = PARITY_NONE;
	param.ucRxTriggerLevel = UART1_LEVEL_1_BYTE;
	
	#if 0
	sysprintf("\nSelect baud rate 9600/38400/57600/115200/230400/460800 [0/1/2/3/4/5]\n");
	ch = sysGetChar();
	ch -= 0x30;
	param.uBaudRate = comBaudRate[ch];  
	#else
	param.uBaudRate = 28800; 
	#endif
	
	rtval = uartOpen(&param); 
	if(rtval != 0) 
	{
		_UART_ShowErrInfo(rtval);
		return;
	}
	
	rtval = uartIoctl(param.ucUartNo, UART_IOC_SETUART1FULLMODEM, 0, 0);
	if(rtval != 0) 
	{
		_UART_ShowErrInfo(rtval);
		return;
	}
	
	memset(buf, 0, sizeof(buf));
	i = index = 0;
	
	len = strlen((PINT8) initString);
	rtval = uartWrite(param.ucUartNo, initString_1, len);
	if(rtval < 0) 
		_UART_ShowErrInfo(rtval);
	
	//sysDelay(100);
	sysprintf("init command sent, waiting for reply...\n");
	while(1)
	{
		i = uartRead(param.ucUartNo, buf + index, sizeof(buf) - index);
		if(i > 0)
		{
			index += i;
			for(j = 0; j < index; j++)
			{ 
				sysprintf("%02x ", *(buf + j));
				if ( ( *(buf + j) == 'O' ) && ( *(buf + (j + 1) ) == 'K' ) )	
					mflag = 1;
			}
			sysprintf("\n");
			
			if (mflag)
				break;
		}		
	}		
	sysprintf("OK returned\n");	
}

static VOID UART_HW_Flowcontrol(VOID)
{
	INT rtval, ch, cnt, i = 0/*, j*/;
	
	/* Configure UART channel 1 */
	param.uFreq = 15000000;
	param.uBaudRate = comBaudRate[3];  // 115200bps
	param.ucUartNo = UART1;
	param.ucDataBits = DATA_BITS_8;
	param.ucStopBits = STOP_BITS_1;
	param.ucParity = PARITY_NONE;
	param.ucRxTriggerLevel = UART1_LEVEL_1_BYTE;
	rtval = uartOpen(&param); 
	if (rtval != 0) 
	{
		_UART_ShowErrInfo(rtval);
		return;
	}
	
	/* Enable UART1 H/W flow control */
	rtval = uartIoctl(param.ucUartNo, UART_IOC_ENABLEHWFLOWCONTROL, 0, 0);
	if (rtval != 0) 
	{
		_UART_ShowErrInfo(rtval);
		return;
	}
	
	/* Initialize TX data. These data are the same with _1k_testdata.TXT . */
	for (i = 0; i < MASSDATASIZE; i++)
	{
		if ( ( (i + 1) & 0xFF ) == 0x18 )    /* hyperterminal issue */
			TXDATA[i] = 0x19;
		else if ( ( (i + 1) & 0xFF ) == 0 )  /* Don't give value, 1 */
			TXDATA[i] = 1;
		else
			TXDATA[i] = i + 1;		
	}
	
	while (1)
	{
		sysprintf("\nSelect test item TX/RX [0/1]\n");
		ch = sysGetChar();
		if ( (ch != '0') && (ch != '1') )	
			continue;
		
		if(ch == '0') 
		{
			/* 
				TX test, CTS(I). 
				UART library should define debug message, UART_FLOWCONTROL_DEBUG.
				
				..... test with HyperTerminal failed, no CTS signal occurred that PC buffer isn't full
			*/			
			sysprintf("\n Any key start to test\n");
	        ch = sysGetChar();
	
			i = 0;
			while (i < MASSDATASIZE)
			//while(1)
			{
				rtval = uartWrite(param.ucUartNo, TXDATA + i, 16); 
				//rtval = uartWrite(param.ucUartNo, TXDATA, 50); 
				if (rtval > 0)	
				{
					i += rtval;
					//sysprintf("Tx[%d]\r", i);	
				}
			}
			sysprintf("\nTx [%d] complete ...\n", i);			
		}
		else  
		{
			/* 
				RX test, RTS(O). 
				First, UART1 hyperterminal must send data. Then user can make a decision to receive
				data from hyperterminal or not.
			*/
			sysprintf("\n Start RX test\n");
			i = 0;			
			while (1)
			{
				rtval = uartRead(param.ucUartNo, RXDATA + i, 100);  
				if (rtval > 0)
				{	
					i += rtval;
					//sysprintf("Rx[%d]byte\r", i);  /* Important. Debug info cause side effect */					
					if (i == MASSDATASIZE)
			       		break;
			    }
			    
#if 0			    
			    if (i != 0)
			    {
			    	/* step by step to get data */
			    	sysprintf("Any key to receive data or [q] to exit\n");
			    	ch = sysGetChar();	
			    	if (ch == 'q')
			    		break;
			    	sysprintf("Rx[%d]byte\n", i);	
			    }
#endif			    
			}
			
			/* Compare data */			
			cnt = 0;
			for (i = 0; i < MASSDATASIZE; i++)
			{
				if (RXDATA[i] != TXDATA[i])
					cnt++;	
			}
			
			if (cnt)
				sysprintf("\n compare fail [%d]\n", cnt);
			else
				sysprintf("\n compare [%d] success\n", i);	
		}
		
		sysprintf("\n\n  Continue this test item [y/n]\n");
		ch = sysGetChar();
		if ( (ch == 'n') || (ch == 'N') )
			break;
	}		
}

static VOID UART_SW_Flowcontrol(VOID)
{
	INT rtval, ch, cnt, i = 0, temp;
	
	/* Configure UART channel 1 */
	param.uFreq = 15000000;
	param.uBaudRate = comBaudRate[3];  // 115200bps
	param.ucUartNo = UART1;
	param.ucDataBits = DATA_BITS_8;
	param.ucStopBits = STOP_BITS_1;
	param.ucParity = PARITY_NONE;
	param.ucRxTriggerLevel = UART1_LEVEL_1_BYTE;
	rtval = uartOpen(&param); 
	if (rtval != 0) 
	{
		_UART_ShowErrInfo(rtval);
		return;
	}
	
	/* Enable UART1 S/W flow control */
	rtval = uartIoctl(param.ucUartNo, UART_IOC_ENABLESWFLOWCONTROL, 0, 0);
	if(rtval != 0) 
	{
		_UART_ShowErrInfo(rtval);
		return;
	}

	for (i = 0; i < MASSDATASIZE; i++)
	{
		temp = (i + 1) & 0xFF;
		if (temp == 0x18)       /* hyperterminal issue */
			TXDATA[i] = 0x55;
		else if (temp == 0)     /* Don't give value, 1 */
			TXDATA[i] = 1;
		else if (temp == 0x11)  /* S/W flow control issue, Xon  */
			TXDATA[i] = 0x55;	
		else if (temp == 0x13)  /* S/W flow control issue, Xoff */
			TXDATA[i] = 0x55;
		else
			TXDATA[i] = temp;				
	}
	
	while (1)
	{
		sysprintf("\nSelect test item TX/RX [0/1]\n");
		ch = sysGetChar();
		if ( (ch != '0') && (ch != '1') )	
			continue;
	
		if (ch == '0')
		{
			/*
				TX test with Xon/Xoff.
			*/
			sysprintf("\n Any key start to test\n");
	        ch = sysGetChar();
	
			i = 0;
			while (i < MASSDATASIZE)
			{
				rtval = uartWrite(param.ucUartNo, TXDATA + i, 16); 
				if (rtval > 0)	
				{
					i += rtval;
					//sysprintf("Tx[%d]\r", i);	
				}
			}
			sysprintf("\nTx [%d] complete ...\n", i);			
		}
		else
		{
			/*
				RX test with Xon/Xoff.
			*/
			sysprintf("\n Start RX test\n");
			memset(RXDATA, 0, MASSDATASIZE);
			i = 0;			
			while (1)
			{
				rtval = uartRead(param.ucUartNo, RXDATA + i, 100);	
				if (rtval > 0)
				{	
					i += rtval;
					//sysprintf("Rx[%d]byte\n", i);
			       	if (i == MASSDATASIZE)
			    		break;
			    }
			    
#if 1			    
			    if (i != 0)
			    {
			    	sysprintf("Any key to receive data or [q] to exit\n");
			    	sysprintf("Rx[%d]byte\n", i);
			    	ch = sysGetChar();	
			    	if (ch == 'q')
			    		break;
			    }
#endif			    
			}
			
			/* Compare data */			
			cnt = 0;
			for (i = 0; i < MASSDATASIZE; i++)
			{
				if (RXDATA[i] != TXDATA[i])
					cnt++;	
			}
			
			if (cnt)
				sysprintf("compare fail [%d]\n", cnt);
			else
				sysprintf("compare [%d] success\n", i);				
		}
		
		sysprintf("\n\n  Continue this test item [y/n]\n");
		ch = sysGetChar();
		if ( (ch == 'n') || (ch == 'N') )
			break;
	}	
}

INT diag_uart(VOID)
{
	INT item;
	
#if 0 
	WB_PLL_T sysClock;

	sysClock.pll0 = PLL_200MHZ;
	sysClock.pll1 = PLL_133MHZ;
	sysClock.cpu_src = CPU_FROM_PLL0;
	sysClock.ahb_clk = AHB_CPUCLK_1_2;
	sysClock.apb_clk = APB_AHB_1_2;
	sysSetPLLConfig(&sysClock);
#endif

#ifdef CACHE_ON
	sysDisableCache();
	sysInvalidCache();
	//sysEnableCache(CACHE_WRITE_BACK);  
	sysEnableCache(CACHE_WRITE_THROUGH); 
	sysprintf("\n Cache on ...\n");	
#endif		

	//sysSetTimerReferenceClock(TIMER0, 15000000);
	//sysStartTimer(TIMER0, 100, PERIODIC_MODE);	
		
	/* Initial UART struct */
	uartInit(); 
	
	do 
	{
		_UART_TestItem();	
		item = sysGetChar();		
		switch(item)
		{
			/* 2007.11.20 add, PT23 HHWu */
			case '0':
				_UART_Testmsg(0);  
				UART_External_Loopback();
				break;
			
			case '1':
				_UART_Testmsg(1);  
				UART_RX();              /* Test UART channel 1~4 */ 
				break;
				
			case '2':
				_UART_Testmsg(2);  
				UART_TX();              /* Test UART channel 1~4 */ 
				break;
				
			case '3':   
				_UART_Testmsg(3);  
				UART_GetRegister();     /* Test UART channel 0~4 */       
				break;	
				
			case '4':   
				_UART_Testmsg(4);  
				UART_Line_Break();      /* Test UART channel 1~4 */      
				break;	
				
			case '5':
				_UART_Testmsg(5);  
				UART_Modem_Loopback();  /* Test UART channel 1 & 3 */
				break;
				
			case '6':
				_UART_Testmsg(6);  
				//UART_High_Speed();      /* Only UART channel 1 */
				UART_High_Speed_External_Loopback();
				break;
				
			case '7':	
				_UART_Testmsg(7);  
				UART_IrDA();            /* Only UART channel 2 */             
				break;  
				
			case '8':	
				_UART_Testmsg(8);
				UART_Modem_Test();      /* Only UART channel 1 */             
				break;
				
			#if 1  /* 2007.11.20 mark, PT23 HHWu */
			/* TX Mass Data Test*/
			case 'a':
				UART_TX_MassDATATest();  /* test with UART_RX_MassDATATest() */
				break;
			
			/* RX Mass Data Test*/
			case 'b':
				UART_RX_MassDATATest();  /* test with UART_TX_MassDATATest() */
				break;
			#endif		
				
			case 'c':
				_UART_Testmsg(12);
				UART_HW_Flowcontrol();
				break;
				
			case 'd':
				_UART_Testmsg(13);
				UART_SW_Flowcontrol();
				break;
				
			default:	
				break;			
		}
			
	}while(item != 27);  // ESC	

	return 0;
}	 
  
#if 1  /* 2007.11.20 mark, PT23 HHWu */ 
static void UART_TX_MassDATATest (void)
{
	int i, rtval, ch;
	
	/* initialize TX data */
	for (i = 0; i < MASSDATASIZE; i++)
	{
		if ( ( (i + 1) & 0xFF ) == 0x18 )  /* hyperterminal issue */
			TXDATA[i] = 0x19;
		else
			TXDATA[i] = i + 1;	
	}
		
	/* Configure UART */
	param.uFreq = 15000000;
	param.uBaudRate = comBaudRate[3];  /* 115200 bps */
	param.ucUartNo = UART2;
	param.ucDataBits = DATA_BITS_8;
	param.ucStopBits = STOP_BITS_1;
	param.ucParity = PARITY_NONE;
	if (param.ucUartNo == UART1)
		param.ucRxTriggerLevel = UART1_LEVEL_1_BYTE;
	else
		param.ucRxTriggerLevel = LEVEL_1_BYTE;	
	
	rtval = uartOpen(&param); 
	if (rtval != 0) 
	{
		_UART_ShowErrInfo(rtval);
		return;
	}	
	
	/* TX interrupt mode */
	rtval = uartIoctl(param.ucUartNo, UART_IOC_SETTXMODE, UARTINTMODE, 0);	
	if (rtval != 0) 
	{
		_UART_ShowErrInfo(rtval);
		return;
	}
	
	/* Start Tx test */
	sysprintf("\n Any key start to test\n");
	ch = sysGetChar();
	
	i = 0;
	while (i < MASSDATASIZE)
	{
		rtval = uartWrite(param.ucUartNo, TXDATA + i, 10); 
		if (rtval > 0)	
		{
			i += rtval;
			//sysprintf("Tx[%d]\r", i);	
		}
	}
	sysprintf("\nTx [%d] complete ...\n", i);
}

static void UART_RX_MassDATATest (void)
{
	int i, rtval, ch, cnt = 0;
	
	/* initialize TX data */
	for (i = 0; i < MASSDATASIZE; i++)
	{
		if ( ( (i + 1) & 0xFF ) == 0x18 )  /* hyperterminal issue */
			TXDATA[i] = 0x19;
		else
			TXDATA[i] = i + 1;	
	}
	
	/* Configure UART */
	param.uFreq = 15000000;
	param.uBaudRate = comBaudRate[3];  /* 115200 bps */
	param.ucUartNo = UART2;
	param.ucDataBits = DATA_BITS_8;
	param.ucStopBits = STOP_BITS_1;
	param.ucParity = PARITY_NONE;
	if (param.ucUartNo == UART1)
		param.ucRxTriggerLevel = UART1_LEVEL_1_BYTE;
	else
		param.ucRxTriggerLevel = LEVEL_8_BYTES;  // LEVEL_1_BYTE	
	
	rtval = uartOpen(&param); 
	if (rtval != 0) 
	{
		_UART_ShowErrInfo(rtval);
		return;
	}	
	
	rtval = uartIoctl(param.ucUartNo, UART_IOC_SETRXMODE, UARTINTMODE, 0);	
	if(rtval != 0) 
	{
		_UART_ShowErrInfo(rtval);
		return;
	}

	/* Start Rx test */
	sysprintf("\n Any key start to test\n");
	ch = sysGetChar();
	
	i = 0;
	while (i < MASSDATASIZE)
	{
		rtval = uartRead(param.ucUartNo, RXDATA + i, 100);
		if (rtval > 0)	
		{
			i += rtval;
			//sysprintf("Rx[%d]\r", i);	
		}
	}
	sysprintf("\nRx [%d] complete ...\n", i);
	
	/* Compare data */			
	for (i = 0; i < MASSDATASIZE; i++)
	{
		if (RXDATA[i] != TXDATA[i])
			cnt++;	
	}
	
	if (cnt)
		sysprintf("compare fail [%d]\n", cnt);
	else
		sysprintf("compare success\n");	
}
#endif

/*
    If test with time out mechanism, set UART TX & RX as interrupt mode.
*/
static VOID UART_External_Loopback(VOID)
{
	char Baudrate_Info[9][7] = {"1200","2400","4800","9600","19200","38400","57600","115200","230400"};
	int Baudrate[9] = {1200,2400,4800,9600,19200,38400,57600,115200,230400};
	int volatile stime, etime;
    
    char LCR_Info[40][10] = {"N,5,1","N,5,1.5","N,6,1","N,6,2","N,7,1","N,7,2","N,8,1","N,8,2",
    						 "OP,5,1","OP,5,1.5","OP,6,1","OP,6,2","OP,7,1","OP,7,2","OP,8,1","OP,8,2",
    						 "EP,5,1","EP,5,1.5","EP,6,1","EP,6,2","EP,7,1","EP,7,2","EP,8,1","EP,8,2",
    						 "SOP,5,1","SOP,5,1.5","SOP,6,1","SOP,6,2","SOP,7,1","SOP,7,2","SOP,8,1","SOP,8,2",
    						 "SEP,5,1","SEP,5,1.5","SEP,6,1","SEP,6,2","SEP,7,1","SEP,7,2","SEP,8,1","SEP,8,2"};
	unsigned char Item_LCR[40] = {0x00,0x04,0x01,0x05,0x02,0x06,0x03,0x07,
    							  0x08,0x0C,0x09,0x0D,0x0A,0x0E,0x0B,0x0F,
    							  0x18,0x1C,0x19,0x1D,0x1A,0x1E,0x1B,0x1F,
    							  0x28,0x2C,0x29,0x2D,0x2A,0x2E,0x2B,0x2F,
    							  0x38,0x3C,0x39,0x3D,0x3A,0x3E,0x3B,0x3F};    						 
	
	int i, j, k, ch, retval, val, MaxChar;		
	UINT8 RXD, TXD;
	
	sysprintf("\n\nPress any key to exit test while test be performed!\n");
	while (1)
	{
		sysprintf("\nSelect UART channel [1/2/3/4]\n");
		ch = sysGetChar();
		if ( (ch >= '1') && (ch <= '4') )
		{
			sysprintf("UART[%c] selected\n\n", ch);	
			break;
		}
	}
	
#if 0
	
	/* UART polling mode */
	sysprintf("\nPolling mode\n\n");
	
	for (i = 0; i < 9; i++)
	{
		for (j = 0; j < 40; j++)
		{
			sysprintf("%s, %s: ", Baudrate_Info[i], LCR_Info[j]);
			
			/* configure UART */
			param.uFreq = 15000000;     
			param.uBaudRate = Baudrate[i];			
			param.ucUartNo = ch - 0x30;  			
			val = Item_LCR[j] & 0x03;
			param.ucDataBits = val;				
			val = Item_LCR[j] & 0x04;			
			param.ucStopBits = val;			
			val = Item_LCR[j] & 0x38;	
			param.ucParity = val;			
			if (param.ucUartNo == UART1)
				param.ucRxTriggerLevel = UART1_LEVEL_1_BYTE;  
			else
				param.ucRxTriggerLevel = LEVEL_1_BYTE;  	
			
			retval = uartOpen(&param); 
			if (retval != 0) 
			{
				_UART_ShowErrInfo(retval);
				return;
			}
			
			retval = uartIoctl(param.ucUartNo, UART_IOC_SETTXMODE, UARTPOLLMODE, 0); 
			retval = uartIoctl(param.ucUartNo, UART_IOC_SETRXMODE, UARTPOLLMODE, 0);
			
			val = Item_LCR[j] & 0x03;
		    if (val == 0x00)  	   /* character length 5 bits */
		    	MaxChar = 0x20;
		    else if (val == 0x01)  /* character length 6 bits */
		    	MaxChar = 0x40;	
		    else if( val == 0x02)  /* character length 7 bits */
		    	MaxChar = 0x80;
		    else if (val == 0x03)  /* character length 8 bits */
		    	MaxChar = 0x100;	
		    	
		    for (k = 0; k < MaxChar; k++)
		    {
		    	/* start TX */
		    	TXD = k;
		    	retval = uartWrite(param.ucUartNo, &TXD, 1);
				if(retval < 0)
				{
					sysprintf("TX [0x%x] error!\n", k);
					break;
				}
				
				/* start RX */
				retval = uartRead(param.ucUartNo, &RXD, 1);
				if(retval < 0)
				{
					sysprintf("RX [0x%x] error!\n", k);
					break;					
				}
				
				if (RXD != TXD)
				{
					sysprintf("Data comparison error!\n");
					break;	
				}
		    }
		    
		    if (k == MaxChar)
				sysprintf("OK\n");
			else
				sysprintf ("FAIL (outChar=%0x, inChar=%0x)!\n", TXD, RXD);				
		}		
	}
		
#else
		
	/* UART interrupt mode */	
	sysprintf("\nInterrupt mode\n\n");
	
	stime = sysGetTicks(TIMER0);	
	for (i = 0; i < 9; i++)
	{
		//i = 7;  // ..... test    115200
		for (j = 0; j < 40; j++)
		{
			//j = 6;  // ..... test    N,8,1
			sysprintf("%s, %s: ", Baudrate_Info[i], LCR_Info[j]);
			
			/* configure UART */
			param.uFreq = 15000000;     
			param.uBaudRate = Baudrate[i];			
			param.ucUartNo = ch - 0x30;  			
			val = Item_LCR[j] & 0x03;
			param.ucDataBits = val;				
			val = Item_LCR[j] & 0x04;			
			param.ucStopBits = val;			
			val = Item_LCR[j] & 0x38;	
			param.ucParity = val;			
			if (param.ucUartNo == UART1)
				param.ucRxTriggerLevel = UART1_LEVEL_1_BYTE;  
			else
				param.ucRxTriggerLevel = LEVEL_1_BYTE;  	
			
			retval = uartOpen(&param); 
			if (retval != 0) 
			{
				_UART_ShowErrInfo(retval);
				return;
			}
			
			retval = uartIoctl(param.ucUartNo, UART_IOC_FLUSH_RX_BUFFER, 0, 0);  
			retval = uartIoctl(param.ucUartNo, UART_IOC_SETTXMODE, UARTINTMODE, 0);
			retval = uartIoctl(param.ucUartNo, UART_IOC_SETRXMODE, UARTINTMODE, 0);
			
			val = Item_LCR[j] & 0x03;
		    if (val == 0x00)  	   /* character length 5 bits */
		    	MaxChar = 0x20;
		    else if (val == 0x01)  /* character length 6 bits */
		    	MaxChar = 0x40;	
		    else if( val == 0x02)  /* character length 7 bits */
		    	MaxChar = 0x80;
		    else if (val == 0x03)  /* character length 8 bits */
		    	MaxChar = 0x100;	
		    	
		    stime = sysGetTicks(TIMER0);
		    for (k = 0; k < MaxChar; k++)
		    {
		    	/* start TX */
		    	TXD = k;
		    	retval = uartWrite(param.ucUartNo, &TXD, 1);
				if(retval < 0)
				{
					sysprintf("TX [0x%x] error!\n", k);
					break;
				}
				
				/* start RX, must receive data */
				while (1)
				{
					retval = uartRead(param.ucUartNo, &RXD, 1);
					if (retval < 0)
					{
						sysprintf("RX [0x%x] error!\n", k);
						break;					
					}
					else if (retval == 1)
					{
						//sysprintf("RX[0x%x]\n", RXD);
						stime = etime;
						break;	
					}
					
					etime = sysGetTicks(TIMER0);
					if (etime - stime >= 100)  /* time out 1sec */
					{
						sysprintf("\n\nRX time out!\n");
						goto EXITTEST;
					}
					
					if (inpw(REG_UART0_LSR) & 0x01)	
					{
						sysprintf("\n\nExit test!\n");
						goto EXITTEST;	
					}	
				}
				
				if (RXD != TXD)
				{
					sysprintf("Data comparison error!\n");
					break;	
				}
		    }
		    
		    if (k == MaxChar)
				sysprintf("OK\n");
			else
				sysprintf ("FAIL (outChar=%0x, inChar=%0x)!\n", TXD, RXD);				
		}		
	}
#endif	

EXITTEST:
	
	uartRelease(param.ucUartNo);
	sysprintf("Close UART[%d]\n", param.ucUartNo);
	
	sysprintf("\nAny key continually ...\n");
	ch = sysGetChar();			
}
